<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
  <title>Promise并发</title>
</head>
<body>
<img data-src="https://robohash.org/104.236.21.134.png" alt="">
<img data-src="https://robohash.org/104.236.21.13.png" alt="">
<img data-src="https://robohash.org/104.236.2114.png" alt="">
<img data-src="https://robohash.org/104.236.2.134.png" alt="">
<img data-src="https://robohash.org/104.236.1.134.png" alt="">
<img data-src="https://robohash.org/104.23621.134.png" alt="">
<img data-src="https://robohash.org/104.2361.134.png" alt="">
<img data-src="https://robohash.org/104.2.21.134.png" alt="">
<img data-src="https://robohash.org/104.21.134.png" alt="">
<img data-src="https://robohash.org/10436.21.134.png" alt="">
<img data-src="https://robohash.org/14.236.21.134.png" alt="">
<img data-src="https://robohash.org/10.236.21.134.png" alt="">
<img data-src="https://robohash.org/04.236.21.134.png" alt="">
<img data-src="https://robohash.org/104.236.2113.png" alt="">
<img data-src="https://robohash.org/104.236.234.png" alt="">
<img data-src="https://robohash.org/104.236.134.png" alt="">
<img data-src="https://robohash.org/104.221.134.png" alt="">
<img data-src="https://robohash.org/104.23134.png" alt="">
<script>
  function loadImg(callback) {
    return function (dom, url) {
      return new Promise((resolve, reject) => {
        var img = new Image();
        img.src = url;
        if (img.complete) {
          callback(img, dom)
          resolve();
        }
        img.onload = function () {
          callback(img, dom);
          resolve();
        }
        img.onerror = reject;
      })
    }
  }

  function showImg(img, dom) {
    dom.src = img.src;
  }

  // var imgDOMs = document.querySelectorAll('img');
  // imgDOMs.forEach(imgDOM=>{
  //   var url = imgDOM.dataset.src;
  //   loadImg(imgDOM,url,showImg);
  // })
  var imgDOMs = Array.prototype.slice.call(document.querySelectorAll('img'));
  var urls = imgDOMs.map(item => item.dataset.src);

  class PromisePoll {
    constructor(limit, handler) {
      this.limit = limit;
      this.pool = [];
      this.rest = [];
      this.handler = handler; // 用于产生Promise
    }

    start(urls,doms) {
      this.rest = urls;
      this.doms = doms;
      while (this.pool.length < this.limit) {
        let url = this.rest.shift();
        let dom = doms.shift();
        this.setTask(dom,url)
      }
      let races = Promise.race(this.pool);
      return this.run(races);
    }

    setTask(dom,url) {
      if (!url) return;
      let task = this.handler(dom,url);
      this.pool.push(task);
      console.log(`${url} 开始, 当前并发数:${this.pool.length}`)
      task.then(res => {
        this.pool.splice(this.pool.indexOf(task), 1);
        console.log(`${url} 结束, 当前并发数:${this.pool.length}`)
      })
    }

    run(races) {
      races.then(res => {
        let url = this.rest.shift();
        let dom = this.doms.shift();
        this.setTask(dom,url);
        return this.run(Promise.race(this.pool));
      })
    }
  }

  const pool = new PromisePoll(3, loadImg(showImg));
  pool.start(urls,imgDOMs);
</script>
</body>
</html>
